package arcturus;

import java.awt.GradientPaint;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.swing.JOptionPane;

import acm.graphics.GObject;

import inputHandlers.keyInputHandler;
import inputHandlers.mouseClickHandler;
import mapProperties.BulletEntity;
import mapProperties.Entity;
import mapProperties.bulletThreadCleaner;

public class GameLogic extends Thread{	
	
	private Map currentMap;
	private AI enemyHandler = new AI();
	private keyInputHandler userKeyHandler = new keyInputHandler(this);
	private mouseClickHandler userClickHandler = new mouseClickHandler(this);
	private Game gp; 
	private Boolean rungame = true;
	
	private double velocityX = 0;
	private double velocityY = 0;
	public int jumpCount = 0;
	private ScheduledExecutorService se =   Executors.newScheduledThreadPool(1);
	private Collection<ScheduledFuture<BulletEntity>> runningBullets = new ArrayList<ScheduledFuture<BulletEntity>>();
	//====================================
	//====================================
	//====================================
	
	public GameLogic(Game gp){
		this.gp = gp;	
		currentMap = new Map(enemyHandler, gp);
		try{
			currentMap.loadMockup();
		}
		catch(Exception ex){
			JOptionPane.showMessageDialog(gp, ex.toString(), "ERROR", JOptionPane.ERROR_MESSAGE);
		}
		
		gp.addKeyListeners(userKeyHandler);
		gp.addMouseListeners(userClickHandler);
		
	}
	//====================================
	//====================================
	//====================================
	public boolean isGameChange(){
		return true;
	}
	//====================================
	//====================================
	//====================================
	public void cancelGame(Boolean yes){
		this.rungame = yes;
	}
	//====================================
	//====================================
	//====================================
	public void run(){//TODO we have to walk before we run wa wa wa, ohh charley brown
				
	}
	
	
	//====================================
	//====================================
	//====================================
	
	public void playerActions(){
		
		
	}
	
	//====================================
	//====================================
	//====================================
	
	public void enemyActions(){
		
	
	}
	//====================================
	//====================================
	//====================================
	
	
	// When the user shoots the x and y are known, so i'm not sure
	// if we need this method.
	public void userAims(){
		
		
	}
	
	//====================================
	//====================================
	//====================================
	
	private void userShoots(int  x, int y){
		GObject temp;
		
		this.spawnBullet(((int)this.currentMap.theHuman.x), ((int)this.currentMap.theHuman.y), x, y);
		//System.out.println(((int)this.currentMap.theHuman.x)+ " "+ ((int)this.currentMap.theHuman.y)+" "+ x+" "+ y);
		/*
		if(this.currentMap.isColliding(x, y)){
			temp = (GObject) this.currentMap.getValueAt(x, y);			
			if(temp!= null){				
				this.gp.remove(temp);
				this.currentMap.remove(String.valueOf(temp.hashCode()));
			}
		}
		*/	
	}
	
	//====================================
	//====================================
	//====================================
	private void userMoves(KeyEvent k){
		//left
		if(k.getKeyCode() == 37 || k.getKeyCode() == 65){			
			//if(!this.currentMap.isCollidingNotWith(-8, 0, this.currentMap.theHuman)){
				this.currentMap.theHuman.x = this.currentMap.theHuman.x - 8;
			//}
			
		}	
		
		// Right
		if(k.getKeyCode() == 39 || k.getKeyCode() == 68){		
			//if(!this.currentMap.isCollidingNotWith(8, 0,  this.currentMap.theHuman)){		
				this.currentMap.theHuman.x = this.currentMap.theHuman.x + 8;
			//}
		}
		
		// Up
		if(k.getKeyCode() == 38 || k.getKeyCode() == 87){
			/*
			if(velocityY > -12)
				// First Jump
				if(jumpCount == 0){
					velocityY -= 7;
					jumpCount++;
					//Double jump
				} else if(jumpCount == 1){
					velocityY -= 4;
					jumpCount++;
				}	
			*/
			//if(!this.currentMap.isCollidingNotWith(0, -7, this.currentMap.theHuman)){		
				this.currentMap.theHuman.y = this.currentMap.theHuman.y - 7;
			//}
			}
		//down
		if(k.getKeyCode() == 83){	
			//if(!this.currentMap.isCollidingNotWith(0, 7, this.currentMap.theHuman)){		
				this.currentMap.theHuman.y = this.currentMap.theHuman.y + 7;
			//}
			}
		try{
			this.currentMap.entityMoved(this.currentMap.theHuman);
		}
		catch(Exception ex){
			JOptionPane.showMessageDialog(gp, ex.toString(), "ERROR", JOptionPane.ERROR_MESSAGE);
		}
		
	}
	//====================================
	//====================================
	//====================================
	
	
	
	//====================================
	//====================================
	//====================================
	private void spawnBullet(int xorg, int yorg, int tox, int toy){
		ExecutorService es = Executors.newCachedThreadPool();		
		BulletEntity be= new BulletEntity(xorg, yorg, tox, toy, "bullet.png", this.gp, this.currentMap);
		this.runningBullets.add((ScheduledFuture<BulletEntity>)this.se.scheduleWithFixedDelay(be, 10, 10, TimeUnit.MILLISECONDS));
		es.execute(bulletThreadCleaner.getInstance(this.runningBullets, this.se));
	}
	
	//====================================
	//====================================
	//====================================
	public void userJumps(){
		/*
		if(currentMap.user.isOnGround()){
			currentMap.user.setyVelocity(-15);
			currentMap.user.setOnGround(false);
		}
		*/
	}
	//====================================
	//====================================
	//====================================
	public void userCrouches(){
		
	}
	//====================================
	//====================================
	//====================================
	public void userReloads(){
		
	}
	//====================================
	//====================================
	//====================================
	public void keyEventPreformed(KeyEvent e){
		this.userMoves(e);		
	}
	//====================================
	//====================================
	//====================================
	public void mouseEventPreformed(MouseEvent arg0){		
		this.userShoots(arg0.getX(), arg0.getY());		
	}
	//====================================
	//====================================
	//====================================
	/*
	public void receiveKeyBoard(String input){
		if(input == "a" || input == "d"){
			//userMoves(input);
		} else if(input == "w"){
			userJumps();
		} else if(input == "s"){
			userCrouches();
		} else if(input == "r"){
			userReloads();
		}
			
	}
	*/
	
	
}

